package com.jrx.anytxn.transaction.controller.api;


import com.jrx.anytxn.accounting.dto.GlInterfaceExcpReportRes;
import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.exception.TxnRuntimeException;
import com.jrx.anytxn.i18n.response.TxnPage;
import com.jrx.anytxn.i18n.response.TxnRespResult;
import com.jrx.anytxn.redisson.service.RedissonLockService;
import com.jrx.anytxn.redisson.util.LockType;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import com.jrx.anytxn.transaction.constant.TransErrMsgConstant;
import com.jrx.anytxn.transaction.dto.common.CommonReq;
import com.jrx.anytxn.transaction.dto.payment.*;
import com.jrx.anytxn.transaction.handler.IPaymentHandler;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.concurrent.TimeUnit;

/**
 * 还款处理
 *
 * @author haopu.zheng
 * date  2019/8/6
 **/
@Api(tags = "还款相关接口")
@RestController
@RequestMapping(value = "/api/transaction/repayment")
public class PaymentController {

    private static final Logger logger = LoggerFactory.getLogger(PaymentController.class);

    @Autowired
    private IPaymentHandler paymentHandler;
    @Autowired
    private RedissonLockService redissonLockService;

    @ApiOperation(value = "逾期试算", notes = "逾期试算")
    @PostMapping(value = "/delinquencyTrial")
    public TxnRespResult<DelinquencyTrialRes> delinquencyTrial(@Valid @RequestBody DelinquencyTrialReq paymentTrialReq) throws TxnException {
        logger.info("逾期还款试算开始:流水号->{}", paymentTrialReq.getSeqNo());
        TxnRespResult<DelinquencyTrialRes> delinquencyTrialResTxnRespResult = new TxnRespResult<>();
        delinquencyTrialResTxnRespResult.getSuccess(paymentHandler.overdueTrail(paymentTrialReq));
        return delinquencyTrialResTxnRespResult;
    }

    @ApiOperation(value = "提前结清试算", notes = "提前结清试算")
    @PostMapping(value = "/advanceSettleTrial")
    public TxnRespResult<AdvanceSettleTrialRes> advanceSettleTrial(@Valid @RequestBody PaymentTrialReq paymentTrialReq) throws TxnException {
        logger.info("提前结清还款试算开始:流水号->{}", paymentTrialReq.getSeqNo());
        TxnRespResult<AdvanceSettleTrialRes> advanceSettleTrialResTxnRespResult = new TxnRespResult<>();
        advanceSettleTrialResTxnRespResult.getSuccess(paymentHandler.preterminationTrail(paymentTrialReq));
        return advanceSettleTrialResTxnRespResult;
    }

    /**
     * 逾期还款
     *
     * @param delinquencyPaymentReq 逾期还款请求
     * @return com.jrx.anytxn.common.data.TxnRespResult<com.jrx.anytxn.transaction.dto.payment.PaymentRes>
     * @author : zhenghaopu
     * date: 2019/9/25
     */
    @ApiOperation(value = "逾期还款", notes = "逾期还款")
    @PostMapping(value = "/delinquencyRepayment")
    public TxnRespResult<PaymentRes> delinquencyRepayment(@Valid @RequestBody DelinquencyPaymentReq delinquencyPaymentReq) throws TxnException {
        logger.info("逾期还款开始:流水号->{}", delinquencyPaymentReq.getSeqNo());
        String lockKey = String.format(TransBizConstant.PAYMENT_REDIS_LOCK, delinquencyPaymentReq.getTenantId(), delinquencyPaymentReq.getUserId(),
                delinquencyPaymentReq.getChannel());
        logger.info("RedissionLock key:{}",lockKey);
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(TransBizConstant.PAYMENT_REDIS_LOCK_WAITE_TIME,
                    TransBizConstant.PAYMENT_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            logger.info("获取RedissionLock key:{},lockFlag:{}",lockKey,lockFlag);
            if (!lockFlag) {
                logger.error(TxnRespCode.TRANSACTION_PROCESSING.getMsg());
                throw new TxnBizException(TxnRespCode.TRANSACTION_PROCESSING.getCode(), TxnRespCode.TRANSACTION_PROCESSING.getMsg());
            }
            TxnRespResult<PaymentRes> paymentResTxnRespResult = new TxnRespResult<>();
            PaymentRes paymentRes = paymentHandler.overdueRepayment(delinquencyPaymentReq);
            paymentResTxnRespResult.getSuccess(paymentRes);
            return paymentResTxnRespResult;
        } catch (InterruptedException e) {
            String msg = String.format(TransErrMsgConstant.GET_REDIS_LOCK_ERROR, lockKey);
            logger.error("异常信息:", e);
            throw new TxnException(msg);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 提前结清还款
     *
     * @param paymentReq 提前结清还款req
     * @return com.jrx.anytxn.common.data.TxnRespResult<com.jrx.anytxn.transaction.dto.payment.PaymentRes>
     * @author : zhenghaopu
     * date: 2019/9/25
     */
    @ApiOperation(value = "提前结清还款", notes = "提前结清还款")
    @PostMapping(value = "/advanceSettleRepayment")
    public TxnRespResult<PaymentRes> advanceSettleRepayment(@Valid @RequestBody PaymentReq paymentReq) throws TxnException {
        logger.info("提前结清还款开始:流水号->{}", paymentReq.getSeqNo());
        String lockKey = String.format(TransBizConstant.PAYMENT_REDIS_LOCK, paymentReq.getTenantId(), paymentReq.getUserId(),
                paymentReq.getChannel());
        logger.info("RedissionLock key:{}",lockKey);
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(TransBizConstant.PAYMENT_REDIS_LOCK_WAITE_TIME,
                    TransBizConstant.PAYMENT_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            logger.info("获取RedissionLock key:{},lockFlag:{}",lockKey,lockFlag);
            if (!lockFlag) {
                logger.error(TxnRespCode.TRANSACTION_PROCESSING.getMsg());
                throw new TxnBizException(TxnRespCode.TRANSACTION_PROCESSING.getCode(), TxnRespCode.TRANSACTION_PROCESSING.getMsg());
            }
            TxnRespResult<PaymentRes> paymentResTxnRespResult = new TxnRespResult<>();
            PaymentRes paymentRes = paymentHandler.preterminationRepayment(paymentReq);
            paymentResTxnRespResult.getSuccess(paymentRes);
            return paymentResTxnRespResult;
        } catch (InterruptedException e) {
            String msg = String.format(TransErrMsgConstant.GET_REDIS_LOCK_ERROR, lockKey);
            logger.error("异常信息:", e);
            throw new TxnException(msg);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 还款状态查询
     *
     * @param paymentStatusQueryReq 还款状态查询req
     * @return com.jrx.anytxn.common.data.TxnRespResult<com.jrx.anytxn.transaction.dto.payment.PaymentStatusQueryRes>
     * @author : zhenghaopu
     * date: 2019/9/25
     */
    @ApiOperation(value = "还款状态查询", notes = "还款状态查询")
    @PostMapping(value = "/paymentStatusQuery")
    public TxnRespResult<PaymentStatusQueryRes> paymentStatusQuery(@Valid @RequestBody PaymentStatusQueryReq paymentStatusQueryReq) throws TxnException {
        logger.info("还款状态查询开始:流水号->{}", paymentStatusQueryReq.getSeqNo());
        TxnRespResult<PaymentStatusQueryRes> result = new TxnRespResult<>();
        result.setStartTime(System.currentTimeMillis());
        PaymentStatusQueryRes paymentStatusQueryRes = paymentHandler.getPaymentStatus(paymentStatusQueryReq);
        result.getSuccess(paymentStatusQueryRes);
        return result;
    }

    /**
     * 提前还款试算
     *
     * @param prePayTrialReq
     * @return
     * @throws TxnException
     */
    @ApiOperation(value = "提前还款试算", notes = "提前还款试算")
    @PostMapping(value = "/prePayTrail")
    public TxnRespResult<PrePayTrialRes> prePayTrail(@Valid @RequestBody PrePayTrialReq prePayTrialReq) throws TxnException {
        TxnRespResult<PrePayTrialRes> prePayTrialResTxnRespResult = new TxnRespResult<>();
        PrePayTrialRes res = paymentHandler.prePayTrail(prePayTrialReq);
        prePayTrialResTxnRespResult.getSuccess(res);
        return prePayTrialResTxnRespResult;
    }

    /**
     * 提前还款
     *
     * @param prePayReq
     * @return
     * @throws TxnException
     */
    @ApiOperation(value = "提前还款", notes = "提前还款")
    @PostMapping(value = "/prePay")
    public TxnRespResult<PrePayRes> prePay(@Valid @RequestBody PrePayReq prePayReq) throws TxnException {
        String lockKey = String.format(TransBizConstant.PAYMENT_REDIS_LOCK, prePayReq.getTenantId(), prePayReq.getUserId(),
                prePayReq.getChannel());
        logger.info("RedissionLock key:{}",lockKey);
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(TransBizConstant.PAYMENT_REDIS_LOCK_WAITE_TIME,
                    TransBizConstant.PAYMENT_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            logger.info("获取RedissionLock key:{},lockFlag:{}",lockKey,lockFlag);
            if (!lockFlag) {
                logger.error(TxnRespCode.TRANSACTION_PROCESSING.getMsg());
                throw new TxnBizException(TxnRespCode.TRANSACTION_PROCESSING.getCode(), TxnRespCode.TRANSACTION_PROCESSING.getMsg());
            }
            TxnRespResult<PrePayRes> paymentResTxnRespResult = new TxnRespResult<>();
            PrePayRes prePayRes = paymentHandler.prePay(prePayReq);
            paymentResTxnRespResult.getSuccess(prePayRes);
            return paymentResTxnRespResult;
        } catch (InterruptedException e) {
            String msg = String.format(TransErrMsgConstant.GET_REDIS_LOCK_ERROR, lockKey);
            logger.error("异常信息:", e);
            throw new TxnException(msg);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 正常还款试算
     *
     * @param onDuePayTrialReq
     * @return
     * @throws TxnException
     */
    @ApiOperation(value = "正常还款试算", notes = "正常还款试算")
    @PostMapping(value = "/onDuePayTrial")
    public TxnRespResult<OnDuePayTrialRes> onDuePayTrial(@Valid @RequestBody OnDuePayTrialReq onDuePayTrialReq) throws TxnException {
        TxnRespResult<OnDuePayTrialRes> advanceSettleTrialResTxnRespResult = new TxnRespResult<>();
        OnDuePayTrialRes res = paymentHandler.onDuePayTrial(onDuePayTrialReq);
        advanceSettleTrialResTxnRespResult.getSuccess(res);
        return advanceSettleTrialResTxnRespResult;
    }

    /**
     * 正常还款
     *
     * @param onDuePayReq
     * @return
     * @throws TxnException
     */
    @ApiOperation(value = "正常还款", notes = "正常还款")
    @PostMapping(value = "/onDuePay")
    public TxnRespResult<PaymentRes> onDuePay(@Valid @RequestBody OnDuePayReq onDuePayReq) throws TxnException {
        String lockKey = String.format(TransBizConstant.PAYMENT_REDIS_LOCK, onDuePayReq.getTenantId(), onDuePayReq.getUserId(),
                onDuePayReq.getChannel());
        logger.info("RedissionLock key:{}",lockKey);
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(TransBizConstant.PAYMENT_REDIS_LOCK_WAITE_TIME,
                    TransBizConstant.PAYMENT_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            logger.info("获取RedissionLock key:{},lockFlag:{}",lockKey,lockFlag);
            if (!lockFlag) {
                logger.error(TxnRespCode.TRANSACTION_PROCESSING.getMsg());
                throw new TxnBizException(TxnRespCode.TRANSACTION_PROCESSING.getCode(), TxnRespCode.TRANSACTION_PROCESSING.getMsg());
            }
            TxnRespResult<PaymentRes> paymentResTxnRespResult = new TxnRespResult<>();
            PaymentRes res = paymentHandler.onDuePay(onDuePayReq);
            paymentResTxnRespResult.getSuccess(res);
            return paymentResTxnRespResult;
        } catch (InterruptedException e) {
            String msg = String.format(TransErrMsgConstant.GET_REDIS_LOCK_ERROR, lockKey);
            logger.error("异常信息:", e);
            throw new TxnException(msg);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 还款记录查询
     *
     * @param paymentRecordQueryReq 还款记录查询请求
     * @return 还款记录
     * @throws TxnBizException 业务异常
     */
    @ApiOperation(value = "还款记录查询", notes = "还款记录查询")
    @PostMapping(value = "/repayRecordQuery")
    public TxnRespResult<PaymentRecordQueryRes> queryRepayRecord(@Valid @RequestBody PaymentRecordQueryReq paymentRecordQueryReq) throws TxnBizException {
        TxnRespResult<PaymentRecordQueryRes> paymentResTxnRespResult = new TxnRespResult<>();
        logger.debug("还款记录查询开始 开始时间startTime:{}", paymentResTxnRespResult.getStartTime());
        paymentResTxnRespResult.getSuccess(paymentHandler.queryPaymentRecord(paymentRecordQueryReq));
        logger.debug("还款记录查询结束 返回贷款记录查询响应实体endTime{}", paymentResTxnRespResult.getEndTime());
        return paymentResTxnRespResult;
    }

    /**
     * 逾期欠款明细查询
     *
     * @param commonReq 逾期欠款明细查询请求
     * @return 逾期欠款明细
     * @throws TxnBizException 业务异常
     */
    @ApiOperation(value = "逾期欠款明细查询", notes = "逾期欠款明细查询")
    @PostMapping(value = "/queryDelinquencyDebt")
    public TxnRespResult<DelinquencyDebtQueryRes> queryDelinquencyDebt(@Valid @RequestBody CommonReq commonReq) throws TxnException {
        TxnRespResult<DelinquencyDebtQueryRes> debtQueryResTxnRespResult = new TxnRespResult<>();
        debtQueryResTxnRespResult.getSuccess(paymentHandler.queryDelinquencyDebt(commonReq));
        return debtQueryResTxnRespResult;
    }

    /**
     * 客户欠款查询
     *
     * @param commonReq 通用请求
     * @return 客户欠款
     * @throws TxnBizException 业务异常
     */
    @ApiOperation(value = "客户欠款查询", notes = "客户欠款查询API")
    @PostMapping(value = "/queryCustomerDebt")
    public TxnRespResult<CustomerDebtQueryRes> queryCustomerDebt(@Valid @RequestBody CommonReq commonReq) throws TxnException {
        TxnRespResult<CustomerDebtQueryRes> customerDebtQueryResTxnRespResult = new TxnRespResult<>();
        customerDebtQueryResTxnRespResult.getSuccess(paymentHandler.queryCustomerDebt(commonReq));
        return customerDebtQueryResTxnRespResult;
    }

    /**
     * 客户账单分期试算
     *
     * @param loanStagingTrailReq
     * @return
     * @throws TxnException
     */
    @ApiOperation(value = "账单分期试算", notes = "账单分期试算API")
    @PostMapping(value = "/loanStagingTrail")
    public TxnRespResult<LoanStagingTrailRes> loanStagingTrail(@Valid @RequestBody LoanStagingTrailReq loanStagingTrailReq) throws Exception {
        TxnRespResult<LoanStagingTrailRes> result = new TxnRespResult<>();
        logger.debug("账单分期试算开始 startTime:{}", result.getStartTime());
        LoanStagingTrailRes res = paymentHandler.loanStagingTrail(loanStagingTrailReq);
        logger.debug("账单分期试算结束 endTime:{}", result.getEndTime());
        result.getSuccess(res);
        return result;
    }

    /**
     * 客户账单分期
     *
     * @param loanStagingTrailReq
     * @return
     * @throws TxnException
     */
    @ApiOperation(value = "账单分期", notes = "账单分期API")
    @PostMapping(value = "/loanStaging")
    public TxnRespResult<LoanStagingRes> loanStaging(@Valid @RequestBody LoanStagingTrailReq loanStagingTrailReq) throws Exception {
        String lockKey = String.format(TransBizConstant.PAYMENT_REDIS_LOCK, loanStagingTrailReq.getTenantId(), loanStagingTrailReq.getUserId(),
                loanStagingTrailReq.getChannel());
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(TransBizConstant.PAYMENT_REDIS_LOCK_WAITE_TIME,
                    TransBizConstant.PAYMENT_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            logger.info("获取RedissionLock key:{},lockFlag:{}",lockKey,lockFlag);
            if (!lockFlag) {
                logger.error(TxnRespCode.TRANSACTION_PROCESSING.getMsg());
                throw new TxnBizException(TxnRespCode.TRANSACTION_PROCESSING.getCode(), TxnRespCode.TRANSACTION_PROCESSING.getMsg());
            }
            TxnRespResult<LoanStagingRes> result = new TxnRespResult<>();
            logger.debug("账单分期处理开始 startTime:{}", result.getStartTime());
            LoanStagingRes res = paymentHandler.loanStaging(loanStagingTrailReq);
            logger.debug("账单分期处理结束 endTime{}", result.getEndTime());
            result.getSuccess(res);
            return result;
        } catch (InterruptedException e) {
            String msg = String.format(TransErrMsgConstant.GET_REDIS_LOCK_ERROR, lockKey);
            logger.error("异常信息:", e);
            throw new TxnException(msg);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 账单还款
     *
     * @param billPayReq
     * @return
     * @throws TxnException
     */
    @ApiOperation(value = "账单还款", notes = "账单还款")
    @PostMapping(value = "/billPay")
    public TxnRespResult<PaymentRes> billPay(@Valid @RequestBody BillPayReq billPayReq) throws TxnException {
        billPayReq.checkBizType();
        String lockKey = String.format(TransBizConstant.PAYMENT_REDIS_LOCK, billPayReq.getTenantId(), billPayReq.getUserId(),
                billPayReq.getChannel());
        logger.info("RedissionLock key:{}",lockKey);
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(TransBizConstant.PAYMENT_REDIS_LOCK_WAITE_TIME,
                    TransBizConstant.PAYMENT_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            logger.info("获取RedissionLock key:{},lockFlag:{}",lockKey,lockFlag);
            if (!lockFlag) {
                logger.error(TxnRespCode.TRANSACTION_PROCESSING.getMsg());
                throw new TxnBizException(TxnRespCode.TRANSACTION_PROCESSING.getCode(), TxnRespCode.TRANSACTION_PROCESSING.getMsg());
            }
            TxnRespResult<PaymentRes> paymentResTxnRespResult = new TxnRespResult<>();
            PaymentRes res = paymentHandler.billPay(billPayReq);
            paymentResTxnRespResult.getSuccess(res);
            return paymentResTxnRespResult;
        } catch (InterruptedException e) {
            String msg = String.format(TransErrMsgConstant.GET_REDIS_LOCK_ERROR, lockKey);
            logger.error("异常信息:", e);
            throw new TxnException(msg);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 第三方还款
     *
     * @param thirdPartyPaymentRep
     * @return thirdPartyPaymentRes
     * @throws TxnException
     */
    @ApiOperation(value = "第三方还款", notes = "第三方还款API")
    @PostMapping(value = "/thirdPartyPayment")
    public TxnRespResult<ThirdPartyPaymentRes> thirdPartyPayment(@Valid @RequestBody ThirdPartyPaymentRep thirdPartyPaymentRep) throws TxnException {
        String lockKey = String.format(TransBizConstant.PAYMENT_REDIS_LOCK, thirdPartyPaymentRep.getTenantId(), thirdPartyPaymentRep.getUserId(),
                thirdPartyPaymentRep.getChannel());
        logger.info("RedissionLock key:{}",lockKey);
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(TransBizConstant.PAYMENT_REDIS_LOCK_WAITE_TIME,
                    TransBizConstant.PAYMENT_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            logger.info("获取RedissionLock key:{},lockFlag:{}",lockKey,lockFlag);
            if (!lockFlag) {
                logger.error(TxnRespCode.TRANSACTION_PROCESSING.getMsg());
                throw new TxnBizException(TxnRespCode.TRANSACTION_PROCESSING.getCode(), TxnRespCode.TRANSACTION_PROCESSING.getMsg());
            }
            TxnRespResult<ThirdPartyPaymentRes> result = new TxnRespResult<>();
            logger.debug("第三方还款 开始 startTime:{}", result.getStartTime());
            ThirdPartyPaymentRes res = paymentHandler.thirdPartyPayment(thirdPartyPaymentRep);
            logger.debug("第三方还款 结束 endTime{}", result.getEndTime());
            result.getSuccess(res);
            return result;
        } catch (InterruptedException e) {
            String msg = String.format(TransErrMsgConstant.GET_REDIS_LOCK_ERROR, lockKey);
            logger.error("异常信息:", e);
            throw new TxnException(msg);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 第三方还款查询
     *
     * @param thirdPartyPaymentQueryReq 第三方还款查询请求
     * @return 客户欠款
     * @throws TxnBizException 业务异常
     */
    @ApiOperation(value = "第三方还款查询", notes = "第三方还款查询API")
    @PostMapping(value = "/thirdPartyPaymentQuery")
    public TxnRespResult<ThirdPartyPaymentQueryRes> thirdPartyPaymentQuery(@Valid @RequestBody ThirdPartyPaymentQueryReq thirdPartyPaymentQueryReq) throws TxnException {
        TxnRespResult<ThirdPartyPaymentQueryRes> result = new TxnRespResult<>();
        result.getSuccess(paymentHandler.thirdPartyPaymentQuery(thirdPartyPaymentQueryReq));
        return result;
    }


    /**
     * 主动还款准入校验
     * @param paymentAccessCheckReq 主动还款准入校验请求
     * @return
     * @throws TxnBizException 业务异常
     */
    @ApiOperation(value = "主动还款准入校验", notes = "主动还款准入校验API")
    @PostMapping(value = "/paymentAccessCheck")
    public TxnRespResult<PaymentAccessCheckRes> thirdPartyPaymentQuery(@Valid @RequestBody PaymentAccessCheckReq paymentAccessCheckReq) throws TxnException {
        TxnRespResult<PaymentAccessCheckRes> result = new TxnRespResult<>();
        logger.debug("主动还款准入校验 开始 startTime:{}",result.getStartTime());
        PaymentAccessCheckRes res = paymentHandler.paymentAccessCheck(paymentAccessCheckReq);
        logger.debug("主动还款准入校验 结束 endTime{}",result.getEndTime());
        result.getSuccess(res);
        return result;
    }

    /**
     * 提前还下期
     * @param billPrepayNextReq 提前还下期账单
     * @return
     * @throws TxnBizException 业务异常
     */
    @ApiOperation(value = "提前还下期账单", notes = "提前还下期API")
    @PostMapping(value = "/billPrepayNext")
    public TxnRespResult<BillPrepayNextRes> billPrepayNext(@Valid @RequestBody BillPrepayNextReq billPrepayNextReq) throws TxnException {
        billPrepayNextReq.checkBizType();

        String lockKey = String.format(TransBizConstant.PAYMENT_REDIS_LOCK, billPrepayNextReq.getTenantId(), billPrepayNextReq.getUserId(),
                billPrepayNextReq.getChannel());
        logger.info("RedissionLock key:{}",lockKey);
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(TransBizConstant.PAYMENT_REDIS_LOCK_WAITE_TIME,
                    TransBizConstant.PAYMENT_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            logger.info("获取RedissionLock key:{},lockFlag:{}",lockKey,lockFlag);
            if (!lockFlag) {
                logger.error(TxnRespCode.TRANSACTION_PROCESSING.getMsg());
                throw new TxnBizException(TxnRespCode.TRANSACTION_PROCESSING.getCode(), TxnRespCode.TRANSACTION_PROCESSING.getMsg());
            }
            TxnRespResult<BillPrepayNextRes> result = new TxnRespResult<>();
            logger.debug("提前还下期账单 开始 startTime:{}",result.getStartTime());
            BillPrepayNextRes res = paymentHandler.billPrepayNext(billPrepayNextReq);
            logger.debug("提前还下期账单 结束 endTime{}",result.getEndTime());
            result.getSuccess(res);
            return result;
        } catch (InterruptedException e) {
            String msg = String.format(TransErrMsgConstant.GET_REDIS_LOCK_ERROR, lockKey);
            logger.error("异常信息:", e);
            throw new TxnException(msg);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 退款
     * @param refundReq 退款
     * @return
     * @throws TxnBizException 业务异常
     */
    @ApiOperation(value = "退款", notes = "退款API")
    @PostMapping(value = "/refund")
    public TxnRespResult<RefundRes> refund(@Valid @RequestBody RefundReq refundReq) throws Exception {
        String lockKey = String.format(TransBizConstant.PAYMENT_REDIS_LOCK, refundReq.getTenantId(), refundReq.getUserId(),
                refundReq.getChannel());
        logger.info("RedissionLock key:{}",lockKey);
        RLock lock = redissonLockService.getRLock(lockKey, LockType.REENTRANT_LOCK);
        try {
            boolean lockFlag = lock.tryLock(TransBizConstant.PAYMENT_REDIS_LOCK_WAITE_TIME,
                    TransBizConstant.PAYMENT_REDIS_LOCK_LESS_TIME, TimeUnit.SECONDS);
            logger.info("获取RedissionLock key:{},lockFlag:{}",lockKey,lockFlag);
            if (!lockFlag) {
                logger.error(TxnRespCode.TRANSACTION_PROCESSING.getMsg());
                throw new TxnBizException(TxnRespCode.TRANSACTION_PROCESSING.getCode(), TxnRespCode.TRANSACTION_PROCESSING.getMsg());
            }
            TxnRespResult<RefundRes> result = new TxnRespResult<>();
            logger.debug("退款 开始 startTime:{}",result.getStartTime());
            RefundRes res = paymentHandler.refund(refundReq);
            logger.debug("退款 结束 endTime{}",result.getEndTime());
            result.getSuccess(res);
            return result;
        } catch (InterruptedException e) {
            String msg = String.format(TransErrMsgConstant.GET_REDIS_LOCK_ERROR, lockKey);
            logger.error("异常信息:", e);
            throw new TxnException(msg);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 账单还款试算
     * @param billPayTrailReq
     * @return
     * @throws TxnException
     */
    @ApiOperation(value = "账单还款试算", notes = "账单还款试算API")
    @PostMapping(value = "/billPayTrail")
    public TxnRespResult<BillPayTrailRes> billPayTrail(@Valid @RequestBody BillPayTrailReq billPayTrailReq) throws TxnException {
        billPayTrailReq.checkBizType();
        TxnRespResult<BillPayTrailRes> result = new TxnRespResult<>();
        logger.debug("账单还款试算 开始 startTime:{}",result.getStartTime());
        BillPayTrailRes res = paymentHandler.billPayTrail(billPayTrailReq);
        logger.debug("账单还款试算 结束 endTime{}",result.getEndTime());
        result.getSuccess(res);
        return result;
    }

    @ApiOperation(value = "客户还款记录查询", notes = "客户还款记录查询API")
    @PostMapping(value = "/custRepaymentQuery")
    public TxnRespResult<CustRepaymentQueryRes> custRepaymentQuery(@Valid @RequestBody CustRepaymentQueryReq custRepaymentQueryReq) throws TxnException {
        TxnRespResult<CustRepaymentQueryRes> result = new TxnRespResult<>();
        logger.debug("客户还款记录查询 开始 startTime:{}",result.getStartTime());
        custRepaymentQueryReq.checkBizType();
        CustRepaymentQueryRes res = paymentHandler.custRepaymentQuery(custRepaymentQueryReq);
        logger.debug("客户还款记录查询 结束 endTime{}",result.getEndTime());
        result.getSuccess(res);
        return result;
    }


    @ApiOperation(value = "结清日期查询", notes = "结清日期查询API")
    @PostMapping(value = "/getEtlSettleDate")
    public TxnRespResult<EtlSettleRes> getEtlSettleDate(@Valid @RequestBody EtlSettleReq etlSettleReq) throws TxnException {
        TxnRespResult<EtlSettleRes> result = new TxnRespResult<>();
        logger.debug("结清日期查询 开始 startTime:{}", result.getStartTime());
        result.getSuccess(paymentHandler.getEtlSettleDate(etlSettleReq));
        logger.debug("结清日期查询 结束 endTime{}", result.getEndTime());
        return result;
    }

    /**
     * 客户借据还款记录
     * @param repaymentQueryReq
     * @return
     * @throws TxnException
     */
    @ApiOperation(value = "客户借据还款记录查询", notes = "客户借据还款记录API")
    @PostMapping(value = "/loanRepaymentQuery")
    public TxnRespResult<LoanRepaymentQueryRes> loanRepaymentQuery(@Valid @RequestBody LoanRepaymentQueryReq repaymentQueryReq) throws TxnException {
        TxnRespResult<LoanRepaymentQueryRes> result = new TxnRespResult<>();
        logger.debug("客户借据还款记录查询开始 startTime:{}", result.getStartTime());
        result.getSuccess(paymentHandler.loanRepaymentQuery(repaymentQueryReq));
        logger.debug("客户借据还款记录查询 结束 endTime{}", result.getEndTime());
        return result;
    }
}
